package com.corner.model.cornerservice.helper;

import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.sdk.android.oss.model.OSSException;
import com.avos.avoscloud.AVFile;
import com.corner.R;
import com.corner.app.App;
import com.corner.app.GlobalParams;
import com.corner.model.cornerservice.domain.CloudFile;
import com.corner.model.cornerservice.domain.User;
import com.corner.model.cornerservice.service.Service;
import com.corner.model.cornerservice.service.exception.BaseException;
import com.corner.model.cornerservice.utils.DigestUtil;
import com.corner.model.cornerservice.utils.ServiceQuery;
import com.corner.model.leancloud.base.BaseBeanHelper;
import com.corner.model.oss.OSSManager;
import com.corner.utils.CollectionUtil;
import com.corner.utils.MD5Util;
import com.corner.utils.SharePreferenceUtil;
import com.corner.utils.ToastUtil;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * User助手
 *
 * @author Administrator
 */
public class UserHelper extends BaseBeanHelper {

    /**
     * 修改用户名
     *
     * @param user
     * @param nickName
     */
    public static Observable<User> changeUsername(final User user, String nickName) {
        user.setUsername(nickName);
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    Service.getInstance().userService.update(user.getObjectId(), user);
                    subscriber.onNext(user);
                } catch (BaseException e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 修改密码
     *
     * @param password
     */
    public static Observable<User> changePassword(final String oldPassword,
                                                  final String password) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    String oldPasswordMD5 = MD5Util.MD5(oldPassword);
                    String passwordMD5 = MD5Util.MD5(password);
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("old_password", oldPasswordMD5);
                    map.put("new_password", passwordMD5);
                    Service.getInstance().userService.updatePassword(User.getCurrentUser().getObjectId(), map);
                    subscriber.onNext(null);
                } catch (BaseException e) {
                    ToastUtil.showCustomToastInDevelop(App.application, e.getMessage());
                    Throwable throwable = null;
                    if (e.getCode().equals(BaseException.PasswordNotMatch)) {
                        throwable = new Throwable(App.application.getString(R.string.change_pasword_oldpassword_error));
                    } else {
                        throwable = new Throwable(App.application.getString(R.string.request_data_error));
                    }
                    subscriber.onError(throwable);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 通过验证码重置密码
     *
     * @param newPassword
     */
    public static Observable<User> changePasswordByPhone(final String phoneNum,
                                                         final String newPassword) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(User.PHONE_NUMBER, phoneNum, ServiceQuery.PROPERTY);
                    List<User> list = Service.getInstance().userService.list(query.toString());
                    if (CollectionUtil.isCollectionEmpty(list)){
                        subscriber.onError(new Throwable(App.application.getString(R.string.user_not_exist)));
                    }else {
                        User user = list.get(0);
                        String password = MD5Util.MD5(newPassword);
                        user.setPassword(password);
                        user.setHasSetPassword(true);
                        Service.getInstance().userService.update(user.getObjectId(), user);
                        subscriber.onNext(user);
                    }
                } catch (BaseException e) {
                    Throwable throwable;
                    if (e.getCode().equals(BaseException.ObjectNotFound)) {
                        throwable = new Throwable(App.application.getString(R.string.user_not_exist));
                    } else {
                        throwable = e;
                    }
                    subscriber.onError(throwable);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());
    }


    /**
     * @param user
     * @param avaterPath
     * @return
     */
    public static Observable<User> changeAvater(User user, String avaterPath) {
        if (TextUtils.isEmpty(avaterPath)) {
            throw new RuntimeException("path is null");
        }
        user.setAvaterPath(avaterPath);
        return saveUser(user);
    }


    public static Observable<User> getPhoneIsHasRegistered(final String phoneNumber) {

        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.setLimit(1);
                    query.equal(User.PHONE_NUMBER, phoneNumber, ServiceQuery.PROPERTY);
                    List<User> list = Service.getInstance().userService.list(query.toString());
                    if (CollectionUtil.isCollectionEmpty(list)){
                        subscriber.onNext(null);
                    }else {
                        SharePreferenceUtil.saveString(App.application, User.CURRENT_USER,
                                JSONObject.toJSONString(list.get(0)));
                        subscriber.onNext(list.get(0));
                    }
                } catch (BaseException e) {
                    if (e.getCode().equals(BaseException.QueryNoResult)){
                        subscriber.onNext(null);
                    }else {
                        subscriber.onError(e);
                    }
                }
            }
        }).subscribeOn(Schedulers.io());
    }


    /**
     * 后台保存用户
     *
     * @param user
     */
    public static Observable<User> saveUser(final User user) {

        return Observable.create(new Observable.OnSubscribe<User>() {

            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    HashMap<String, AVFile> map = null;
                    if (!TextUtils.isEmpty(user.getAvaterPath())) {
                        CloudFile upload = OSSManager.upload(user.getAvaterPath());
                        user.setAvatar(upload);
                    }
                    if (user.getObjectId() != null) {
                        Service.getInstance().userService.update(user.getObjectId(), user);
                    }
                    subscriber.onNext(user);
                } catch (IOException e) {
                    Throwable throwable = new Throwable(App.application.getString(R.string.file_not_found));
                    subscriber.onError(throwable);
                } catch (BaseException e) {
                    subscriber.onError(e);
                } catch (OSSException e) {
                    Throwable throwable = new Throwable("哎呀！图片没有上传成功哦");
                    subscriber.onError(throwable);
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 登录
     *
     * @param phoneNumber
     * @param password
     */
    public static Observable<User> login(final String phoneNumber, final String password) {

        return Observable.create(new Observable.OnSubscribe<User>() {

            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    String passwordMd5 = MD5Util.MD5(password);
                    User user = Service.getInstance().userService.login(phoneNumber, passwordMd5);
                    User.cacheUser(user);
                    subscriber.onNext(user);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                } catch (BaseException e) {
                    Throwable throwable = null;
                    switch (e.getCode()) {
                        case BaseException.PasswordNotMatch:
                        case BaseException.PhoneNumNotFound:
                            throwable = new Throwable(App.application.getString(R.string.login_username_password_error));
                            break;
                        default:
                            throwable = new Throwable(App.application.getString(R.string.request_data_error));
                            break;
                    }
                    subscriber.onError(throwable);
                }
            }
        }).subscribeOn(Schedulers.io());
    }


    /**
     * 根据Id获取Info
     *
     * @param userId
     */
    public static Observable<User> getUser(final Long userId) {

        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    User user = Service.getInstance().userService.get(userId, DigestUtil.getDigest(GlobalParams.deviceId));
                    subscriber.onNext(user);
                } catch (BaseException e) {
                    subscriber.onError(e);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
            }
        }).subscribeOn(Schedulers.io());

    }

    /**
     * 在数据库中保存User
     *
     * @param friendId
     */
    public static void saveUser(Long friendId) {
        com.corner.model.db.User user = App.application.daoSession.getUserDao().load(friendId);
        if (user == null) {
            UserHelper.getUser(friendId).subscribe(new Action1<User>() {
                @Override
                public void call(User user) {
                    if (user != null) {
                        UserHelper.saveUserToDb(user);
                    }
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                }
            });
        } else {
            if (user.getCreateAt() == null || System.currentTimeMillis() - Long.valueOf(user.getCreateAt().getTime()) > 24 * 3600 * 1000) {
                UserHelper.getUser(friendId).subscribe(new Action1<User>() {
                    @Override
                    public void call(User user) {
                        if (user != null) {
                            UserHelper.saveUserToDb(user);
                        }
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                    }
                });
            }
        }
    }

    /**
     * 将user保存到本地数据库zz
     *
     * @param user
     */
    public static void saveUserToDb(User user) {
        com.corner.model.db.User dbUser = new com.corner.model.db.User();
        dbUser.setId(user.getObjectId());
        CloudFile avatar = user.getAvatar();
        if (avatar!=null) {
            com.corner.model.db.CloudFile cloudFile = new com.corner.model.db.CloudFile(null, avatar.getObjectKey(), avatar.getFileUrl(), avatar.getMeta(), avatar.getBucketName());
            App.application.daoSession.getCloudFileDao().insert(cloudFile);
            dbUser.setAvatar(cloudFile);
        }
        dbUser.setPhoneNum(user.getPhoneNum());
        dbUser.setUsername(user.getUsername());
        dbUser.setCreateAt(new Date());
        App.application.daoSession.getUserDao().insertOrReplace(dbUser);
    }

    public static Observable<User> register(final String phoneNumber, final String password) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    User user = new User();
                    user.setPhoneNum(phoneNumber);
                    user.setPassword(MD5Util.MD5(password));
                    user.setHasSetPassword(true);
                    Map<String, Object> map = Service.getInstance().userService.save(user);
                    JSONObject jsonObject = new JSONObject(map);
                    user.setObjectId(jsonObject.getLong(Service.OBJECT_ID));
                    SharePreferenceUtil.saveString(App.application, User.CURRENT_USER, JSONObject.toJSONString(user));
                    subscriber.onNext(null);
                } catch (BaseException|NoSuchAlgorithmException e) {
                    subscriber.onError(e);
                }
            }
        }).subscribeOn(Schedulers.io());
    }
}
